package com.zchu.rxcache;


import com.zchu.rxcache.data.CacheResult;
import com.zchu.rxcache.data.ResultFrom;

import io.reactivex.rxjava3.annotations.Nullable;

import java.io.IOException;
import java.lang.reflect.Type;


/**
 * Cache core
 *
 * @author 赵成柱
 * @since 2021-02-09
 */
class CacheCore {

    @Nullable
    private LruMemoryCache memory;
    @Nullable
    private LruDiskCache disk;

    CacheCore(@Nullable LruMemoryCache memory, @Nullable LruDiskCache disk) {
        this.memory = memory;
        this.disk = disk;
    }


    /**
     * fetch
     *
     * @param key
     * @param type
     * @param <T>
     * @return class
     */
    <T> CacheResult<T> load(String key, Type type) {
        if (memory != null) {
            CacheHolder<T> result = memory.load(key);
            if (result != null) {
                return new CacheResult<>(ResultFrom.Memory, key, result.data, result.timestamp);
            }
        }
        if (disk != null) {
            CacheHolder<T> result = disk.load(key, type);
            if (result != null) {
                return new CacheResult<>(ResultFrom.Disk, key, result.data, result.timestamp);
            }
        }
        return null;
    }

    /**
     * save
     *
     * @param key
     * @param value
     * @param target
     * @param <T>
     * @return class
     */
    <T> boolean save(String key, T value, CacheTarget target) {
        if (value == null) { //If the value is empty, delete it.
            boolean memoryRemove = true;
            if (memory != null) {
                memoryRemove = memory.remove(key);
            }
            boolean diskRemove = true;
            if (disk != null) {
                diskRemove = disk.remove(key);
            }
            return memoryRemove && diskRemove;
        }
        boolean save = false;
        if (target.supportMemory() && memory != null) {
            save = memory.save(key, value);
        }
        if (target.supportDisk() && disk != null) {
            return disk.save(key, value);
        }
        return save;
    }

    /**
     * Include or Not
     *
     * @param key
     * @return boolean
     */
    boolean containsKey(String key) {
        return (memory != null && memory.containsKey(key)) || (disk != null && disk.containsKey(key));
    }

    /**
     * Deleting a Cache
     *
     * @param key
     * @return boolean
     */
    boolean remove(String key) {
        boolean isRemove = true;
        if (memory != null) {
            isRemove = memory.remove(key);
        }
        if (disk != null) {
            isRemove = isRemove & disk.remove(key);
        }
        return isRemove;
    }

    /**
     * Clear the cache.
     *
     * @throws IOException
     */
    void clear() throws IOException {
        if (memory != null) {
            memory.clear();
        }
        if (disk != null) {
            disk.clear();
        }
    }

}
